#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <iomanip>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
#define cout_people out_people
// EasyGame 1.0.5
/*
EasyGame，让游戏开发更简单！
使用时只需将easygame.h加入工程并include <easygame.h>即可！
(PS:本库仅提供逻辑支持和命令行的小部分图形化支持)

最新版本已知BUG(也不算BUG，不准备修改):
当系统自带buff恢复时(-1 or -2参数)，可能还会比原来增加一点。是因为有连锁反应。但作者认为这样也不错，不准备修改。（PS：还是懒）
最新版本已知BUG(准备修改):
无
*/
/*
EasyGame 更新历史
EasyGame 1.0.5
修复了1个upgrade函数内的bug，4个BUFF方面的漏洞，以及8个溢出漏洞。
新增了一些关于upgrade和buff的功能，以及一些内置变量。
新增了类 Architecture(建筑)
新增了命令行图形化(Beta)
新增按键检测
*/
using namespace std;
void clean_all_screen() {
    system("cls");
}
void out_white(int num = 1) {
    for (int i = 0; i < num; i++) {
        cout << "■";
    }
}
void wait_for_enter() {
    system("pause");
}
void out_space(int space_num) {
    for (int i = 0; i < space_num; i++) {
        cout << " ";
    }
}
void out_people(int space_num = 0, bool _fat = false, bool _short = false) {
    //space_num，可以不填，默认为0，可以设置打印的小人距离最左边多少格
    out_space(space_num);
    cout << "      ■      " << endl;
    out_space(space_num);
    if (_short) {
        if (_fat) {
            cout << "■■■■■■■" << endl;
            out_space(space_num);
            cout << "■■■■■■■" << endl;
            out_space(space_num);
            cout << "■■■■■■■" << endl;
            out_space(space_num);
            cout << "  ■      ■  " << endl;
            out_space(space_num);
            cout << "  ■      ■  " << endl;
        }
        else {
            cout << "  ■■■■■  " << endl;
            out_space(space_num);
            cout << "  ■■■■■  " << endl;
            out_space(space_num);
            cout << "  ■■■■■  " << endl;
            out_space(space_num);
            cout << "    ■  ■    " << endl;
            out_space(space_num);
            cout << "    ■  ■    " << endl;
        }
    }
    else {
        if (_fat) {
            cout << "■■■■■■■" << endl;
            out_space(space_num);
            cout << "■■■■■■■" << endl;
            out_space(space_num);
            cout << "■■■■■■■" << endl;
            out_space(space_num);
            cout << "  ■      ■  " << endl;
            out_space(space_num);
            cout << "  ■      ■  " << endl;
            out_space(space_num);
            cout << "  ■      ■  " << endl;
            out_space(space_num);
            cout << "  ■      ■  " << endl;
        }
        else {
            cout << "  ■■■■■  " << endl;
            out_space(space_num);
            cout << "  ■■■■■  " << endl;
            out_space(space_num);
            cout << "  ■■■■■  " << endl;
            out_space(space_num);
            cout << "    ■  ■    " << endl;
            out_space(space_num);
            cout << "    ■  ■    " << endl;
            out_space(space_num);
            cout << "    ■  ■    " << endl;
            out_space(space_num);
            cout << "    ■  ■    " << endl;
            out_space(space_num);
            cout << "    ■  ■    " << endl;
        }
    }
}
bool key_check(char c) {//检测某个按键是否按下，按下就改变输出颜色
    if (!KEY_DOWN(c)) return false;
    else return true;
}

class Player {
public:

    /* 特别注意 */
    /* 部分设置不能直接使用Player.xxx=xxx更改！需要使用指定函数！不然会导致一些连锁作用无法执行！ */
    string name = "Guest";  //角色名 可用Player.name=xxx更改 
    int pid; // 玩家ID(必须设置！直接player.pid=xxx)
    double hp = 0; //生命值  必须使用Player.set_hp设置，如需减少需使用Player.reduce_hp减少指定数值，增加需使用Player.plus_hp增加 
    double dv = 0; //防御值 必须使用Player.set_dv设置，当触发攻击时自动运算并修改 
    string buff = "无BUFF"; //New! 你可以设置Buff来让角色更加强大 此选项供开发者自行调用，可使用Player.buff=xxx 
    double agg = 0; //攻击力 必须使用Player.set_agg设置，会自动修改 
    double chp = 0; //暴击力 必须使用Player.set_chp设置，会自动修改 
    double scp = 0; //超级暴击伤害力 必须使用Player.set_scp设置，会自动修改 
    /* 接下来是特殊属性 */
    double power = 0; //力气，让角色的攻击力、暴击力通过力气提升 必须使用Player.set_power修改 
    double endurance = 0; //耐力，耐力越高，生命值以及暴击伤害越高 必须用Player.set_endurance 修改 
    double agile = 0; //敏捷力。如果敏捷力高，角色可以更高概率躲避暴击 必须用Player.set_agile 
    double intelligence = 0; //智力。如果智力高，敏捷力、耐力都会随之变高。 必须用Player.set_intelligence
    /* 如需初始化特殊属性，可直接用Player.xxx=xxx修改 */
    /* 预设 */
    int player = 0; //需使用Player.set_player(X)设置，可选：1:剑士 2:弓箭手 3:巨人
    int player_buff = 0; //使用Player.set_player_buff(X)设置，可选：1:神清气爽（耐力、力气、智力、敏捷力提高10）2:大快朵颐（通常在食用某种食品后，智力、耐力提高50）3:信心满满（各种属性大幅度提高）4:万念俱灰（各种属性大幅度下降） 
    /* 详细设置 */
    double dwa = 0; //收到攻击时的额外伤害，可直接修改，可用于特殊关卡
    double ms = 0; //移速，可直接修改，供自行调用
    int chr = 0;//暴击可能性(1 几率小 2 随机 3 几率大)，需使用Player.set_chr(X)设置
    /* 自定义高级参数 */
    bool obm = false; //是否打开“荆棘模式”（伤害反弹） 需使用Player.set_obm(True or False)
    bool survival = true; //是否存活。需使用Player.set_survival(True or False)设置
    bool debug = false; //角色是否开启Debug.需使用Player.set_debug(True or False)设置
    bool udh = true; //调用upgrade()函数升级时自动调整攻击力等内容。
    /* 坐标 */
    double x = 0; //坐标X，供2D/3D游戏定位使用 ，直接修改 
    double y = 0; //坐标Y ，供2D/3D游戏定位使用 ，直接修改 
    double z = 0; //坐标Z，，供3D游戏定位使用，直接修改 
    int parid; //正所在哪所建筑(arid)
    /* 等级系统 */
    long long lv = 1; //等级 最好不要直接修改，可以设置默认属性提升，也可以自行操作。需要使用upgrade升级 

    void upgrade(long long upgrade_lv) {
        lv += upgrade_lv;
        if (udh)
        {
            agg += 20.0 * upgrade_lv;
            hp += 50.0 * upgrade_lv;
            dv += 20.0 * upgrade_lv;
        }

        if (debug) {
            cout << name << "升级了！TA升级了" << upgrade_lv << "级！" << endl;
        }

    }
    void set_hp(double sethp) {
        hp = sethp;
        if (debug) {
            cout << "设置了角色" << name << "的生命值为" << hp;
        }
    }
    void reduce_hp(double reducehp) {
        hp -= reducehp;
        if (debug) {
            cout << "将角色" << name << "的生命值减去了" << reducehp << endl;
        }
    }
    void plus_hp(double plushp) {
        hp += plushp;
        if (debug) {
            cout << "将角色" << name << "的生命值增加了" << plushp << endl;
        }
    }
    void set_dv(double setdv) {
        dv = setdv;
        if (debug) {
            cout << "将角色" << name << "的防御值设置为了" << dv << endl;
        }
    }
    void set_buff(string setbuff) {
        buff = setbuff;
        if (debug) {
            cout << "<自定义调用>将角色" << name << "的自定义Buff值设置为了" << setbuff << endl;
            cout << "自定义调用时务必注意：在自定义函数中修改BUFF时需要使用指针或返回值返回调用，不要在这里卡住，然后报错。" << endl;
        }
    }
    void set_agg(double setagg) {
        agg = setagg;
        if (debug) {
            cout << "将角色" << name << "的攻击力设置为了" << agg << endl;
        }

    }
    void set_chp(double setchp) {
        chp = setchp;
        if (debug) {
            cout << "将角色" << name << "的暴击力设置为了" << agg << endl;
        }
    }
    void set_scp(double setscp) {
        scp = setscp;
        if (debug) {
            cout << "将角色" << name << "的超级暴击力设置为了" << scp << endl;
        }
    }
    void set_power(double setpower) {
        if (setpower < power) {
            power = setpower;
            agg -= (power - setpower) * 5;
            chp -= (power - setpower) * 5;
        }
        else if (setpower > power) {
            power = setpower;
            agg += (power - setpower) * 5;
            chp += (power - setpower) * 5;
        }
        if (debug) {
            cout << "将角色" << name << "的力气设置为了" << power << endl;
        }
    }
    void set_endurance(double setendurance) {
        if (setendurance < endurance) {
            endurance = setendurance;
            hp -= (endurance - setendurance) * 10;
            chp -= (endurance - setendurance) * 5;
        }
        else if (setendurance > endurance) {
            endurance = setendurance;
            hp += (endurance - setendurance) * 10;
            chp += (endurance - setendurance) * 5;
        }
        if (debug) {
            cout << "将角色" << name << "的耐力设置为了" << endurance << endl;
        }
    }
    void set_agile(double setagile) {
        agile = setagile;
        if (debug) {
            cout << "将角色" << name << "的敏捷力设置为了" << agile << endl;
        }
    }
    void set_intelligence(double setintelligence) {
        intelligence = setintelligence;
        set_agile(agile + (intelligence - setintelligence) * 5);
        set_endurance(endurance + (intelligence - setintelligence) * 8);
        if (debug) {
            cout << "将角色" << name << "的智力设置为了" << intelligence << endl;
        }
    }
    void set_player(int player) {
        if (player == 1) {
            // 默认角色：剑士 
            set_hp(100.00);
            set_agg(15.05);
            set_dv(5.25);
            name = "剑士";
        }
        else if (player == 2) {
            // 默认角色：弓箭手
            set_hp(80.00);
            set_agg(22.00);
            set_dv(5.00);
            name = "弓箭手";
        }
        else {
            // 默认角色：巨人 
            set_hp(500.50);
            set_agg(25.05);
            set_dv(0);
            name = "巨人";
        }
    }
    void set_player_buff(int buff) {
        if (debug) {
            cout << name << "的系统自带BUFF被改为参数:" << buff << endl;
        }
        if (buff == 1) {
            // 神清气爽
            set_agile(agile + 10);
            set_endurance(endurance + 10);
            set_intelligence(intelligence + 10);
            set_power(power + 10);
        }
        else if (buff == 2) {
            // 大快朵颐 
            set_endurance(endurance + 50);
            set_intelligence(intelligence + 50);
        }
        else if (buff == 3) {
            // 信心满满(恢复请使用buff4)
            set_endurance(endurance + 100);
            set_agile(agile + 50);
            set_power(power + 300);
        }
        else if (buff == 4) {
            // 万念俱灰(恢复请使用buff3)
            set_endurance(endurance - 100);
            set_agile(agile - 50);
            set_power(power - 300);
        }
        else if (buff == -1) {
            // 恢复神清气爽buff之前的状态
            set_agile(agile - 10);
            set_endurance(endurance - 10);
            set_intelligence(intelligence - 10);
            set_power(power - 10);
        }
        else if (buff == -2) {
            // 恢复大快朵颐
            set_endurance(endurance - 50);
            set_intelligence(intelligence - 50);
        }
    }
    int set_chr(int setchr) {
        // 1 非常小 2 随机 3 很大
        chr = setchr;
        return 1;
    }
    void set_obm(bool setobm) {
        obm = setobm;
        if (debug) {
            cout << name << "的OBM值被设置为了" << obm << endl;
        }
    }
    int set_survival(bool setsurvival) {
        if (setsurvival != true) {
            survival = false;
            if (debug) {
                cout << name << "的存活值被设置为了" << setsurvival << " 此角色已退出游戏" << endl;
            }

        }
        else {
            survival = true;
        }
        return survival;
    }
    int set_debug(bool setdebug) {
        if (setdebug) {
            debug = true;
        }
        return 1;
    }
    int ua(Player aPlayer) {
        // 角色被攻击
        // aPlayer>攻击角色的另一个角色
        if (survival && aPlayer.survival) {
            double za = 0; //最后受到的攻击力
            za += aPlayer.agg;
            za -= dv;
            za -= rand() % 5;
            if (za <= 0) {
                if ((rand() % 5) == 1) {
                    return -1; //-1代表免疫了 
                }
                // 有几率免疫，如果没有免疫，就将攻击力提升
                za += aPlayer.agg;
                za -= dv;
                za -= rand() % 3;
                if (za <= 0) {
                    // 实在无法计算，返回-2，说明比赛不公平，无法进行
                    if (debug) {
                        cout << "太不公平了！通过护盾的抵御，攻击被瓦解!" << endl;
                    }
                    return -2;
                }
            }
            // 设置好最后受到的攻击后 
            // 判断暴击与超级暴击
            srand((int)time(0));
            if (chp != 0) {
                if (agile > 10) {
                    //结束暴击 
                }
                else {


                    if (chr == 1) {
                        if (rand() % 100 == 18) {
                            za = aPlayer.chp;
                        }
                    }
                    if (chr == 2) {
                        int randnum = rand() % 100;
                        if (randnum == 18 || randnum == 12 || randnum == 48 || randnum == 69 || randnum == 89 || randnum == 99) {
                            za = aPlayer.chp;
                        }
                    }
                    if (chr == 3) {
                        int randnum = rand() % 100;
                        if (randnum > 50 && randnum < 80) {
                            za = aPlayer.chp;
                        }
                    }
                }
            }
            int randnum2 = rand() % 100;
            if (aPlayer.scp != 0) {
                if (randnum2 == 1) {
                    za = aPlayer.scp;
                }
            }

            if (debug) {
                cout << "角色" << name << "即将受到" << za << "点攻击。" << endl;
            }
            hp -= za;
            if (debug) {
                cout << "角色" << name << "的血量变为" << hp << "点。" << endl;
            }
            if (hp <= 0) {
                survival = false; //自动设置False
                if (debug) {
                    if (survival) {
                        cout << name << "在与" << aPlayer.name << "的作战中死了。" << endl;
                    }

                }
            }
            return 1;
        }
        else {
            if (debug) {
                cout << "角色" << name << "或者角色" << aPlayer.name << "已经死了" << endl;
            }
        }
    }

    void print_all() {
        cout << "PRINT_ALL" << endl;
        /* 特别注意 */
        /* 部分设置不能直接使用Player.xxx=xxx更改！需要使用指定函数！不然会导致一些连锁作用无法执行！ */
        cout << "角色名：" << name << endl;  //角色名 可用Player.name=xxx更改 
        cout << "生命值：" << hp << endl; //生命值  必须使用Player.set_hp设置，如需减少需使用Player.reduce_hp减少指定数值，增加需使用Player.plus_hp增加 
        cout << "防御值：" << dv << endl; //防御值 必须使用Player.set_dv设置，当触发攻击时自动运算并修改 
        cout << "自定义BUFF：" << buff << endl; //New! 你可以设置Buff来让角色更加强大 此选项供开发者自行调用，可使用Player.buff=xxx 
        cout << "攻击力：" << agg << endl; //攻击力 必须使用Player.set_agg设置，会自动修改 
        cout << "暴击力：" << chp << endl; //暴击力 必须使用Player.set_chp设置，会自动修改 
        cout << "超级暴击力：" << scp << endl; //超级暴击伤害力 必须使用Player.set_scp设置，会自动修改 
        /* 接下来是特殊属性 */
        cout << "特殊属性列表：" << endl << power << endl; //力气，让角色的攻击力、暴击力通过力气提升 必须使用Player.set_power修改 
        cout << endurance << endl; //耐力，耐力越高，生命值以及暴击伤害越高 必须用Player.set_endurance 修改 
        cout << agile << endl; //敏捷力。如果敏捷力高，角色可以更高概率躲避暴击 必须用Player.set_agile 
        cout << intelligence << endl; //智力。如果智力高，敏捷力、耐力都会随之变高。 必须用Player.set_intelligence
        /* 如需初始化特殊属性，可直接用Player.xxx=xxx修改 */
        /* 预设 */
        cout << "预设列表：" << endl << player << endl; //需使用Player.set_player(X)设置，可选：1:剑士 2:弓箭手 3:巨人
        cout << player_buff << endl; //使用Player.set_player_buff(X)设置，可选：1:神清气爽（耐力、力气、智力、敏捷力提高10）2:大快朵颐（通常在食用某种食品后，智力、耐力提高50） 
        /* 详细设置 */
        cout << "详细设置列表：" << endl;
        cout << dwa << endl; //收到攻击时的额外伤害，可直接修改，可用于特殊关卡
        cout << ms << endl; //移速，可直接修改，供自行调用
        cout << chr << endl;//暴击可能性(1 几率小 2 随机 3 几率大)，需使用Player.set_chr(X)设置
        /* 自定义高级参数 */
        cout << "自定义高级参数：" << endl;
        cout << obm << endl; //是否打开“荆棘模式”（伤害反弹） 需使用Player.set_obm(True or False)
        cout << survival << endl; //是否存活。需使用Player.set_survival(True or False)设置
        cout << debug << endl; //角色是否开启Debug.需使用Player.set_debug(True or False)设置
        /* 坐标 */
        cout << "位置：" << endl;
        cout << x << endl; //坐标X，供2D/3D游戏定位使用 ，直接修改 
        cout << y << endl; //坐标Y ，供2D/3D游戏定位使用 ，直接修改 
        cout << z << endl; //坐标Z，，供3D游戏定位使用，直接修改 
    }
};
class npc {
public:
    // NPC角色
    // NPC功能不够完善，见谅 
    string name; //名字，使用npc.name=XX修改 
    double hp = 0; //生命值，使用npc.set_hp(X)修改 
    double agg = 0; //攻击力，使用npc.set_agg(X)修改 
    double x; //坐标X，供2D/3D游戏定位使用 ，直接修改 
    double y; //坐标Y ，供2D/3D游戏定位使用 ，直接修改 
    double z; //坐标Z，，供3D游戏定位使用，直接修改
    string say[100]; //设置说的话，游戏界面可以通过npc.say[x]获取，更便捷(默认为100句)
    bool survival; //自行修改，用来在游戏里判断存活 
    void set_hp(double sethp) {
        hp = sethp;
    }
    void set_agg(double setagg) {
        agg = setagg;
    }
};
class Prop {
public:
    string name; //道具名称(可直接修改) 
    string introduce;//道具介绍  (可直接修改) 
    int prid;//道具ID(可直接修改)
    /* 使用道具后角色变化 */
    string buff = "无BUFF"; //设置角色会有什么自定义buff(可直接修改)
    int player_buff = 0; //设置角色会新增什么默认buff (直接修改)(详见player类)
    int power = 0; //增加力气值，让角色的攻击力、暴击力通过力气提升 必须使用prop.set_power修改 
    int endurance = 0; //增加耐力值，耐力越高，生命值以及暴击伤害越高 必须用prop.set_endurance 修改 
    int agile = 0; //增加敏捷力值。如果敏捷力高，角色可以更高概率躲避暴击 必须用prop.set_agile 
    int intelligence = 0; //增加智力值。如果智力高，敏捷力、耐力都会随之变高。 必须用prop.set_intelligence
    /* 使用参数 */
    string use_type; //可加上你的使用类型（例如：饮料、食物、药品）
    int use_lv = 0; //限制使用等级 
    void set_power(int setpower) {
        power = setpower;
    }
    void set_endurance(int setendurance) {
        endurance = setendurance;
    }
    void set_agile(int setagile) {
        agile = setagile;
    }
    void set_intelligence(int setintelligence) {
        intelligence = setintelligence;
    }
    int use(Player usePlayer) {
        if (usePlayer.lv >= use_lv) {
            usePlayer.buff = buff;
            usePlayer.player_buff = player_buff;
            usePlayer.set_power(usePlayer.power + power);
            usePlayer.set_intelligence(usePlayer.intelligence + intelligence);
            usePlayer.set_agile(usePlayer.agile + agile);
            usePlayer.set_endurance(usePlayer.endurance + endurance);
            if (usePlayer.debug) {
                cout << "角色" << usePlayer.name << "使用了道具" << name << endl;
            }
            return 1;
        }
        else {
            return 0;//等级不足 
        }
    }

};
class Architecture {
    public:
        string name="Nameless building";
        string introduce;//建筑介绍  (可直接修改) 
        int arid;//建筑ID(可直接修改)
        /* 使用参数 */
        string ar_type; //可加上建筑类型（例如：楼房，小店等）
        int use_lv = 0; //限制进入/使用等级,可直接修改
        int max_id = 100; //最大进入人数，直接修改
        int now_id = 0; //当前进入的人数，系统自动使用并修改
    void ui_show(int space_num,bool high=true,bool big=true) {
        if (high) {
            if (big) {
                for (int i = 0; i < 10; i++) {
                    out_space(space_num);
                    out_white(8);
                    cout << endl;
                }
            }
            else {
                for (int i = 0; i < 10; i++) {
                    out_space(space_num);
                    out_white(5);
                    cout << endl;
                }
            }
        }
        else {
            if (big) {
                for (int i = 0; i < 7; i++) {
                    out_space(space_num);
                    out_white(7);
                    cout << endl;
                }
            }
            else {
                for (int i = 0; i < 5; i++) {
                    out_space(space_num);
                    out_white(4);
                    cout << endl;
                }
            }
        }
    }
    bool go_in(Player Player1) {
        if (Player1.lv >= use_lv) {
            if (now_id >= max_id) {
                if(Player1.debug) cout << "玩家" << Player1.name << "在尝试进入" << name << "的时候不巧碰上高峰期，挤得根本进不去！"<<endl;
                return false;
            }else if (Player1.debug) {
                cout << "玩家" << Player1.name << "进入了" << name << endl;
                now_id++;
                Player1.parid = arid;
                return true;
            }
        }
        else cout << "玩家" << Player1.name << "由于等级不够所以被" << name << "里的保安赶出来了。" << endl;
        return false;
    }
    void go_out(Player Player1) {
        if (Player1.debug) {
            cout << "玩家" << Player1.name << "从" << name << "里出去了。"<<endl;
        }
        now_id--;
        Player1.parid = NULL;
    }
};
void white_all_screen(int max_screen=3198) { //max_screen可以不填，为屏幕覆盖率，可自己测得
    for (int i = 0; i < 3198; i++) {
        cout << "■";
    }
}

